package com.huangfuyi.process.actuator.monitor;

import com.huangfuyi.process.actuator.enums.EPMonitorThreadStatus;
import com.huangfuyi.process.entity.monitor.EPMonitorAliveCheckInfo;
import com.huangfuyi.process.entity.monitor.EPMonitorInfo;

import java.util.ArrayList;
import java.util.Locale;
import java.util.logging.Logger;

/**
 * 流程编排框架的系统线程管理器，实现以下功能：
 * 1、慢任务（执行时间持续超过配置值的节点任务）监控，慢任务线程池监控
 * 2、执行器主线程池的运行状态
 * 3、存活性监控线程相互检测
 */
public class EPMonitorThreadManager {

    private static final Logger log = Logger.getLogger("MonitorThreadManager");

    // 存活性监控线程，这里使用两个存活性监控线程相互监控，防止其中一个异常导致监控系统失效
    private static EPMonitorAliveCheckThread aliveCheckThread1 = new EPMonitorAliveCheckThread("aliveCheckThread1");

    private static EPMonitorAliveCheckThread aliveCheckThread2 = new EPMonitorAliveCheckThread("aliveCheckThread2");

    // 慢任务监控线程
    private static EPMonitorSlowTaskCheckThread slowTaskCheckThread = new EPMonitorSlowTaskCheckThread("slowTaskCheckThread");

    // 检查所有监控线程的存活性
    public static void aliveCheck(ArrayList<EPMonitorAliveCheckInfo> checkResults) {
        try {
            boolean check = monitorThreadStatusCheck(aliveCheckThread1);
            if (!check) {
                aliveCheckThread1.setDestruction(true);
                aliveCheckThread1 = new EPMonitorAliveCheckThread("aliveCheckThread1");
                aliveCheckThread1.start();
                log.warning("监控线程管理器：线程：%s 重启成功。");
            } else {
                log.info("监控线程管理器：线程：%s 运行正常。");
            }

        } catch (Throwable t) {
            log.warning(String.format(Locale.ROOT, "监控线程管理器：线程：%s 检查运行状态失败，原因：%s", aliveCheckThread1.getName(), t.getMessage()));
        }

        try {
            boolean check = monitorThreadStatusCheck(aliveCheckThread2);
            if (!check) {
                aliveCheckThread2.setDestruction(true);
                aliveCheckThread2 = new EPMonitorAliveCheckThread("aliveCheckThread2");
                aliveCheckThread2.start();
                log.warning("监控线程管理器：线程：%s 重启成功。");
            } else {
                log.info("监控线程管理器：线程：%s 运行正常。");
            }

        } catch (Throwable t) {
            log.warning(String.format(Locale.ROOT, "监控线程管理器：线程：%s 检查运行状态失败，原因：%s", aliveCheckThread2.getName(), t.getMessage()));
        }

        try {
            boolean check = monitorThreadStatusCheck(slowTaskCheckThread);
            if (!check) {
                slowTaskCheckThread.setDestruction(true);
                slowTaskCheckThread = new EPMonitorSlowTaskCheckThread("slowTaskCheckThread");
                slowTaskCheckThread.start();
                log.warning("监控线程管理器：线程：%s 重启成功。");
            } else {
                log.info("监控线程管理器：线程：%s 运行正常。");
            }

        } catch (Throwable t) {
            log.warning(String.format(Locale.ROOT, "监控线程管理器：线程：%s 检查运行状态失败，原因：%s", slowTaskCheckThread.getName(), t.getMessage()));
        }
    }

    private static <T> boolean monitorThreadStatusCheck(EPMonitorThread<T> monitorThread) {
        log.info(String.format(Locale.ROOT, "监控线程管理器：开始检查线程：%s 运行状态", monitorThread.getName()));

        try {
            // 若线程存活性为false，则直接返回
            if (!monitorThread.isAlive()) {
                log.warning(String.format(Locale.ROOT, "监控线程管理器：线程：%s 的isAlive结果为false", monitorThread.getName()));
                return false;
            }

            // 若线程被标记为销毁，则返回false
            if (monitorThread.isDestruction()) {
                log.warning(String.format(Locale.ROOT, "监控线程管理器：线程：%s 已被标记为销毁", monitorThread.getName()));
                return false;
            }

            EPMonitorInfo<T> monitorInfo = monitorThread.getMonitorInfo();
            EPMonitorThreadStatus status = monitorInfo.getStatus();
            if (EPMonitorThreadStatus.RUNNING.equals(status)) {
                // 监控线程的运行状态为运行中，且运行时间超过最大允许运行时间，则视为运行异常
                Long startTime = monitorInfo.getStartTime();
                Long maxRunKeepTime = monitorInfo.getMaxRunKeepTime();
                // 这里检测时间增加1000ms防止系统资源紧张未及时唤醒线程
                if (System.currentTimeMillis() - startTime <= maxRunKeepTime + 1000L) {
                    return true;
                } else {
                    log.warning(String.format(Locale.ROOT, "监控线程管理器：线程：%s 运行时间超过最大可运行时间：%d", monitorThread.getName(), maxRunKeepTime));
                    return false;
                }
            } else if (EPMonitorThreadStatus.FINISH.equals(status)) {
                Long endTime = monitorInfo.getEndTime();
                Long runInterval = monitorInfo.getRunInterval();
                // 这里检测时间增加1000ms防止系统资源紧张未及时唤醒线程
                if (System.currentTimeMillis() - endTime <= runInterval + 1000L) {
                    return true;
                } else {
                    log.warning(String.format(Locale.ROOT, "监控线程管理器：线程：%s 在规定的运行时间间隔（%d ms）后，没有重新运行", monitorThread.getName(), runInterval));
                    return false;
                }
            } else {
                return false;
            }

        } catch (Throwable t) {
            log.warning(String.format(Locale.ROOT, "监控线程管理器：线程：%s 存活性检查失败， 原因：%s", monitorThread.getName(), t.getMessage()));
            return false;
        }
    }

    // 初始化监控
    public static void init(){
        // 存活性监控线程会自动检测其他监控线程的存活性，并重新拉起异常线程
        aliveCheckThread1.start();
    }
}
